#ifndef __UpdClient__hpp__
#define __UpdClient__hpp__

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "Log.hpp"

#include <memory>
#include <string>

using namespace MyLogModule;

class UdpClient
{
public:
    UdpClient(std::string ip, std::string port)
    {
        _port = stoi(port.c_str());
        _ip = ip;
    }

    ~UdpClient()
    {
    }

    void Start()
    {
        _socket = ::socket(AF_INET, SOCK_DGRAM, 0);
        if (_socket == -1)
        {
            LOG(FATAL) << "socket create fail";
            Die(SOCKET_ERR);
        }
        // 转换为网络字节序，并设置
        struct sockaddr_in server;
        server.sin_family = AF_INET;
        server.sin_addr.s_addr = ::inet_addr(_ip.c_str());
        server.sin_port = ::htons(_port);

        while(true)
        {
            std::string message;
            std::cout << "Please enter# ";
            std::getline(std::cin,message);
            
            //客户端也要有自己的ip和port,但不需要绑定，因为OS会自动bind
            //服务端要显示的bind，是因为服务器的端口号，必须稳定！必须是众所周知且不能改变轻易改变的!
            ::sendto(_socket,message.c_str(),message.size(),0,CONVERSE(&server),sizeof(server));

            char buffer[1024];
            //虽然上面已经有了sockaddr_in server,但是可能不只有一个服务器哦
            struct sockaddr_in tmp;
            socklen_t len = sizeof(tmp);

            int n = ::recvfrom(_socket,buffer,sizeof(buffer)-1,0,CONVERSE(&tmp),&len);
            if(n > 0)
            {
                buffer[n] = 0;
                //打印服务器回写的
                std::cout << buffer << std::endl;
            }
        }
    }

private:
    int _socket;
    uint16_t _port;
    std::string _ip;
};

#endif